home *** CD-ROM | disk | FTP | other *** search
- Subject: v17i068: Zoo archive program, Part05/10
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
-
- Submitted-by: Rahul Dhesi <bsu-cs!dhesi@iuvax.cs.indiana.edu>
- Posting-number: Volume 17, Issue 68
- Archive-name: zoo2/part05
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then unpack
- # it by saving it into a file and typing "sh file". To overwrite existing
- # files, type "sh file -c". You can also feed this as standard input via
- # unshar, or by typing "sh <file", e.g.. If this archive is complete, you
- # will see the following message at the end:
- # "End of archive 5 (of 10)."
- # Wrapped by rsalz@papaya.bbn.com on Thu Feb 2 18:04:00 1989
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'comment.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'comment.c'\"
- else
- echo shar: Extracting \"'comment.c'\" \(9637 characters\)
- sed "s/^X//" >'comment.c' <<'END_OF_FILE'
- X#ifndef LINT
- Xstatic char sccsid[]="@(#) comment.c 2.14 88/01/24 12:42:13";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
- X*/
- X
- X#include "options.h"
- X#include "portable.h"
- X/* comment() */
- X/* Updates comments */
- X
- X/* buffer size for any one comment line */
- X#define COMMENT_LINE_SIZE 76
- X
- X#define MAX_COMMENT_SIZE 65535
- X#include "zooio.h"
- X#include "various.h"
- X
- X#ifndef NOSIGNAL
- X#include <signal.h>
- X#endif
- X
- X#include "zoo.h"
- X#include "zoofns.h"
- X#include "errors.i"
- X
- X#ifdef LINT_ARGS
- Xvoid show_comment (struct direntry *, ZOOFILE, int, char *);
- Xget_comment (struct direntry *, ZOOFILE, char *);
- Xint needed (char *, struct direntry *, struct zoo_header *);
- X#else
- Xvoid show_comment ();
- Xget_comment ();
- Xint needed ();
- X#endif
- X
- Xvoid comment(zoo_path, option)
- Xchar *zoo_path, *option;
- X{
- X#ifndef NOSIGNAL
- Xint (*oldsignal)();
- X#endif
- XZOOFILE zoo_file; /* stream for open archive */
- Xlong next_ptr; /* pointers to within archive */
- Xlong this_dir_offset; /* pointers to within archive */
- Xstruct direntry direntry; /* directory entry */
- Xstruct zoo_header zoo_header;
- Xint matched = 0; /* any files matched? */
- Xunsigned int zoo_date, zoo_time; /* for restoring archive timestamp */
- Xchar whichname[PATHSIZE]; /* which name to use */
- X#ifdef ZOOCOMMENT
- Xint acmt = 0; /* if changing archive comment */
- X#endif
- X
- X/* on entry option points to first letter */
- Xoption++; /* skip 'c' */
- X#ifdef ZOOCOMMENT
- Xwhile (*option != '\0') {
- X if (*option == 'A') {
- X acmt++; /* changing archive comment */
- X option++;
- X } else
- X prterror ('f', inv_option, *option);
- X}
- X#else
- Xif (*option != '\0')
- X prterror ('f', inv_option, *option);
- X#endif /* ZOOCOMMENT */
- X
- Xif ((zoo_file = zooopen (zoo_path, Z_RDWR)) == NOFILE)
- X prterror ('f', could_not_open, zoo_path);
- X
- X/* save archive timestamp */
- X#ifdef GETUTIME
- Xgetutime (zoo_path, &zoo_date, &zoo_time);
- X#else
- Xgettime (zoo_file, &zoo_date, &zoo_time);
- X#endif
- X
- X/* read header and rewrite with updated version numbers, but ask user to pack
- Xarchive first if archive comment is to be added and header type is 0 */
- X#ifdef ZOOCOMMENT
- Xif (acmt)
- X rwheader (&zoo_header, zoo_file, 0);
- Xelse
- X rwheader (&zoo_header, zoo_file, 1);
- X#else
- Xrwheader (&zoo_header, zoo_file, 1);
- X#endif
- X
- X#ifdef ZOOCOMMENT
- X/* if archive comment being added, handle it and return */
- Xif (acmt) {
- X void do_acmt PARMS ((struct zoo_header *, ZOOFILE, char *));
- X do_acmt (&zoo_header, zoo_file, zoo_path);
- X#ifdef NIXTIME
- X zooclose (zoo_file);
- X setutime (zoo_path, zoo_date, zoo_time); /* restore timestamp */
- X#else
- X settime (zoo_file, zoo_date, zoo_time); /* restore timestamp */
- X zooclose (zoo_file);
- X#endif
- X return;
- X}
- X#endif /* ZOOCOMMENT */
- X
- X/* Loop through and add comments for matching files */
- Xwhile (1) {
- X this_dir_offset = zootell (zoo_file); /* save pos'n of this dir entry */
- X readdir (&direntry, zoo_file, 1); /* read directory entry */
- X next_ptr = direntry.next; /* ptr to next dir entry */
- X
- X /* exit on end of directory chain or end of file */
- X if (next_ptr == 0L || feof(stdin))
- X break;
- X
- X strcpy (whichname, fullpath (&direntry)); /* full pathname */
- X add_version (whichname, &direntry); /* add version suffix */
- X /* add comments for matching non-deleted files */
- X if (!direntry.deleted && needed (whichname, &direntry, &zoo_header)) {
- X matched++;
- X show_comment (&direntry, zoo_file, 1, whichname);
- X get_comment (&direntry, zoo_file, whichname);
- X zooseek (zoo_file, this_dir_offset, 0);
- X#ifndef NOSIGNAL
- X oldsignal = signal (SIGINT, SIG_IGN);
- X#endif
- X fwr_dir (&direntry, zoo_file);
- X#ifndef NOSIGNAL
- X signal (SIGINT, oldsignal);
- X#endif
- X }
- X zooseek (zoo_file, next_ptr, 0); /* ..seek to next dir entry */
- X} /* end while */
- X
- X#ifdef NIXTIME
- Xzooclose (zoo_file);
- Xsetutime (zoo_path, zoo_date, zoo_time); /* restore timestamp */
- X#else
- Xsettime (zoo_file, zoo_date, zoo_time); /* restore timestamp */
- Xzooclose (zoo_file);
- X#endif
- X
- Xif (!matched)
- X printf ("Zoo: %s", no_match);
- X} /* comment */
- X
- X/* show_comment() */
- X/* shows comment on screen. If show=1, says "Current comment is..." */
- X
- Xvoid show_comment (direntry, zoo_file, show, name)
- Xstruct direntry *direntry;
- XZOOFILE zoo_file;
- Xint show;
- Xchar *name; /* name of file for which comment is being added */
- X{
- X if (direntry->cmt_size != 0) {
- X unsigned int i;
- X char ch;
- X int newline = 1;
- X zooseek (zoo_file, direntry->comment, 0);
- X if (show)
- X printf ("Current comment for %s is:\n", name);
- X for (i = 0; i < direntry->cmt_size; i++) {/* show it */
- X ch = zgetc (zoo_file) & 0x7f; /* 7 bits only */
- X if (newline)
- X printf (" |"); /* indent and mark comment lines thus */
- X zputchar (ch);
- X if (ch == '\n')
- X newline = 1;
- X else
- X newline = 0;
- X }
- X if (!newline) /* always terminate with newline */
- X zputchar ('\n');
- X }
- X} /* show_comment() */
- X
- X
- X/* get_comment() */
- X/* Shows user old comment and updates it */
- X
- X/* INPUT:
- X direntry points to current directory entry.
- X zoo_file is archive file.
- X this_path is full pathname of file being updated/added.
- X
- X OUTPUT:
- X Comment is added to file and supplied directory entry is updated
- X with comment size and seek position but directory entry is
- X not written to file. Exceptions: If RETURN is hit as first line,
- X previous comment is left unchanged. If /END is hit, previous
- X comment is superseded, even if new comment is null.
- X*/
- X
- Xchar cmt_prompt[]="[Enter %scomment for %s then type /END]\n";
- X
- Xget_comment (direntry, zoo_file, this_path) /* update comment */
- Xregister struct direntry *direntry;
- XZOOFILE zoo_file;
- Xchar *this_path;
- X{
- X unsigned int line_count = 0; /* count of new comment lines */
- X
- X zooseek (zoo_file, 0L, 2); /* ready to append new comment */
- X#if 0
- X fprintf (stderr, "[Enter comment for %s then type /END]\n", this_path);
- X#else
- X fprintf (stderr, cmt_prompt, "", this_path);
- X#endif
- X while (1) {
- X char cmt_line[COMMENT_LINE_SIZE];
- X int cmt_size;
- X if (fgets (cmt_line, sizeof(cmt_line), stdin) == NULL)
- X break;
- X line_count++;
- X if (line_count == 1) { /* first line typed */
- X if (!strcmp (cmt_line, "\n")) /* exit if first line blank */
- X break;
- X direntry->comment = zootell (zoo_file);
- X direntry->cmt_size = 0;
- X }
- X if (!strcmpi (cmt_line, "/end\n"))
- X break;
- X cmt_size = strlen (cmt_line);
- X if (MAX_COMMENT_SIZE - direntry->cmt_size > cmt_size) {
- X direntry->cmt_size += (unsigned int) cmt_size;
- X if (zoowrite (zoo_file, cmt_line, cmt_size) < cmt_size)
- X prterror ('f', disk_full);
- X }
- X } /* end while */
- X} /* get_comment() */
- X
- X#ifdef ZOOCOMMENT
- X/*
- Xdo_acmt() updates archive comment by showing it to user and
- Xrequesting a new one. Typed input terminates as with file comment,
- Xi.e., empty initial line leaves comment unchanged, case-insensitive
- X"/end" terminates input comment.
- X*/
- Xvoid do_acmt (zoo_header, zoo_file, zoo_path)
- Xstruct zoo_header *zoo_header;
- XZOOFILE zoo_file;
- Xchar *zoo_path;
- X{
- X unsigned int line_count = 0; /* count of new comment lines */
- X void show_acmt PARMS ((struct zoo_header *, ZOOFILE, int));
- X
- X show_acmt (zoo_header, zoo_file, 1); /* show current archive comment */
- X zooseek (zoo_file, 0L, 2); /* ready to append new comment */
- X#if 0
- X fprintf (stderr, "[Enter archive comment for %s then type /END]\n",
- X zoo_path);
- X#else
- X fprintf (stderr, cmt_prompt, "archive ", zoo_path);
- X#endif
- X
- X while (1) {
- X char cmt_line[COMMENT_LINE_SIZE];
- X int cmt_size;
- X if (fgets (cmt_line, sizeof(cmt_line), stdin) == NULL)
- X break;
- X line_count++;
- X if (line_count == 1) { /* first line typed */
- X if (!strcmp (cmt_line, "\n")) /* exit if first line blank */
- X break;
- X zoo_header->acmt_pos = zootell (zoo_file);
- X zoo_header->acmt_len = 0;
- X }
- X if (!strcmpi (cmt_line, "/end\n"))
- X break;
- X cmt_size = strlen (cmt_line);
- X if (MAX_COMMENT_SIZE - zoo_header->acmt_len > cmt_size) {
- X zoo_header->acmt_len += (unsigned int) cmt_size;
- X if (zoowrite (zoo_file, cmt_line, cmt_size) < cmt_size)
- X prterror ('f', disk_full);
- X }
- X } /* end while */
- X zooseek (zoo_file, 0L, 0); /* seek back to beginning */
- X fwr_zooh (zoo_header, zoo_file); /* write update zoo_header */
- X} /* do_acmt() */
- X#endif /* ZOOCOMMENT */
- X
- X/* Prints archive comment. If show==1, says "Current archive comment is:" */
- Xvoid show_acmt (zoo_header, zoo_file, show)
- Xstruct zoo_header *zoo_header;
- XZOOFILE zoo_file;
- Xint show;
- X{
- X if (zoo_header->zoo_start != FIXED_OFFSET && zoo_header->acmt_len > 0) {
- X unsigned int i;
- X char ch;
- X int newline = 1;
- X zooseek (zoo_file, zoo_header->acmt_pos, 0);
- X if (show)
- X printf ("Current archive comment is:\n");
- X for (i = 0; i < zoo_header->acmt_len; i++) {/* show it */
- X ch = zgetc (zoo_file) & 0x7f; /* 7 bits only */
- X if (newline)
- X printf (">> "); /* indent and mark comment lines thus */
- X zputchar (ch);
- X if (ch == '\n')
- X newline = 1;
- X else
- X newline = 0;
- X }
- X if (!newline) /* always terminate with newline */
- X zputchar ('\n');
- X }
- X} /* show_acmt() */
- END_OF_FILE
- if test 9637 -ne `wc -c <'comment.c'`; then
- echo shar: \"'comment.c'\" unpacked with wrong size!
- fi
- # end of 'comment.c'
- fi
- if test -f 'misc.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'misc.c'\"
- else
- echo shar: Extracting \"'misc.c'\" \(9670 characters\)
- sed "s/^X//" >'misc.c' <<'END_OF_FILE'
- X#ifndef LINT
- X/* @(#) misc.c 2.6 88/08/15 16:17:23 */
- Xstatic char sccsid[]="@(#) misc.c 2.6 88/08/15 16:17:23";
- X#endif /* LINT */
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X/* Miscellaneous functions needed by Zoo but not by Ooz */
- X
- X#include "zoo.h"
- X#include "zooio.h"
- X#include "various.h"
- X
- X#include "errors.i"
- X#include "zoofns.h"
- X#ifndef NOSIGNAL
- X#include <signal.h>
- X#endif
- X
- X#ifdef NEEDCTYP
- X#include <ctype.h>
- X#else
- X#include "portable.h"
- X#endif
- X
- X#ifdef LINT_ARGS
- Xint ver_too_high (struct zoo_header *);
- X#else
- Xint ver_too_high ();
- X#endif
- X
- X
- X/*
- Xcalc_ofs() is given a string that (supposedly) begins with a string
- Xof digits. It returns a corresponding numeric value. If no such
- Xstring, it aborts the program with a fatal error message.
- X*/
- Xlong calc_ofs(str)
- Xchar *str;
- X{
- X long retval;
- X char *p;
- X retval = 0L;
- X p = str; /* save for error message */
- X while (isdigit(*str)) {
- X retval = retval * 10L + (*str-'0');
- X str++;
- X }
- X if (*str != '\0')
- X prterror ('f', "Invalid number %s\n", p);
- X return (retval);
- X}
- X
- X/*
- Xchoosefname() decides which filename to use. If a long filename is present,
- Xand if the syntax is that of UNIX, MS-DOS or the portable form, we use it;
- Xelse we use the short filename.
- X*/
- X
- Xchar *choosefname(direntry)
- Xstruct direntry *direntry;
- X{
- X char *retptr; /* pointer to name that we will return */
- X switch (direntry->system_id) {
- X case SYSID_NIX:
- X case SYSID_PORTABLE:
- X case SYSID_MS:
- X retptr = (direntry->namlen != 0) ? direntry->lfname : direntry->fname;
- X break;
- X default:
- X retptr = direntry->fname;
- X break;
- X }
- X return (retptr);
- X} /* choosefname() */
- X
- X/*
- Xcombine() combines a directory name and a filename, making sure the
- Xtwo are separated by a path separator
- X*/
- Xchar *combine(result, dirname, fname)
- Xchar result[], *dirname, *fname;
- X{
- X *result = '\0';
- X if (*dirname != '\0') {
- X#ifdef DIR_LBRACK /* hack for VMS */
- X strcat (result, DIR_LBRACK);
- X
- X /* "/" => "[", "./" => "[." others => "[." */
- X
- X if (dirname[0] == '/') { /* absolute path => "[" */
- X strcat (result, dirname + 1);
- X } else if (dirname[0] == '.' && dirname[1] == '/') {
- X strcat (result, CUR_DIR);
- X strcat (result, dirname + 2);
- X } else {
- X strcat (result, CUR_DIR);
- X strcat (result, dirname);
- X }
- X
- X/* folowing #ifdef block ought to be outside #ifdef DIR_LBRACK, and
- X for loop should then start with p=result. This is currently
- X just a hack for VMS.
- X*/
- X#ifdef DIR_SEP
- X if (DIR_SEP != '/') { /* if char separating dirs is not "/", */
- X char *p;
- X for (p = result+2; *p != '\0'; p++) /* change it to underscore */
- X if (*p == DIR_SEP)
- X *p = '_';
- X }
- X#endif
- X
- X {
- X char *p;
- X for (p = result; *p != '\0'; p++)
- X if (*p == '/')
- X *p = '.';
- X }
- X#else
- X strcat (result, dirname);
- X#endif
- X if (*lastptr(result) != *PATH_CH)
- X strcat(result, PATH_CH);
- X }
- X
- X strcat(result, fname);
- X return (result);
- X}
- X
- X/*
- Xfullpath() accepts a pointer to a directory entry and returns the
- Xcombined directory name + filename. The long filename is used
- Xif available, else the short filename is used.
- X*/
- Xchar *fullpath (direntry)
- Xstruct direntry *direntry;
- X{
- X static char result[PATHSIZE];
- X combine (result,
- X direntry->dirlen != 0 ? direntry->dirname : "",
- X (direntry->namlen != 0) ? direntry->lfname : direntry->fname
- X );
- X return (result);
- X}
- X
- X/*
- Xver_too_high returns true if version of provided archive header is
- Xtoo high for us to manipulate archive
- X*/
- X
- Xint ver_too_high (header)
- Xstruct zoo_header *header;
- X{
- X return (header->major_ver > MAJOR_VER ||
- X (header->major_ver == MAJOR_VER &&
- X header->minor_ver > MINOR_VER));
- X}
- X
- X/*
- Xrwheader() reads archive header, checks consistency, makes sure its
- Xversion number is not too high, updates it if too low, and seeks to
- Xbeginning of first directory entr. If `preserve' is 1, it preserves
- Xthe header type; if `preserve' is 0, it gives a fatal error message
- Xif type is 0.
- X*/
- X
- Xvoid rwheader (header, zoo_file, preserve)
- Xregister struct zoo_header *header;
- XZOOFILE zoo_file;
- Xint preserve;
- X{
- X
- X frd_zooh (header, zoo_file);
- X
- X if ((header->zoo_start + header->zoo_minus) != 0L)
- X prterror ('f', failed_consistency);
- X if (ver_too_high (header))
- X prterror ('f', wrong_version, header->major_ver, header->minor_ver);
- X
- X if (preserve == 0 && header->type == 0)
- X prterror ('f', packfirst);
- X
- X /* We reach here if the archive version is not too high. Now, if it
- X isn't the same as ours, we bring it up to ours so the modified archive
- X will be safe from previous versions of Zoo */
- X
- X if (header->major_ver != MAJOR_VER || header->minor_ver != MINOR_VER) {
- X header->major_ver = MAJOR_VER;
- X header->minor_ver = MINOR_VER;
- X zooseek (zoo_file, 0L, 0); /* seek to beginning */
- X fwr_zooh (header, zoo_file);
- X }
- X zooseek (zoo_file, header->zoo_start, 0); /* seek to where data begins */
- X} /* rwheader */
- X
- X/*
- Xwritedir() write a directory entry with keyboard interrupt disabled
- X*/
- Xvoid writedir (direntry, zoo_file)
- Xstruct direntry *direntry;
- XZOOFILE zoo_file;
- X{
- X#ifndef NOSIGNAL
- X int (*oldsignal)();
- X oldsignal = signal (SIGINT, SIG_IGN);
- X#endif
- X if (fwr_dir (direntry, zoo_file) == -1)
- X prterror ('f', disk_full);
- X#ifndef NOSIGNAL
- X signal (SIGINT, oldsignal);
- X#endif
- X}
- X
- X/*
- Xreaddir() reads a directory entry from an archive. If the directory
- Xentry is invalid and if fail is 1, it causes a fatal error;
- Xelse it returns. Return value is 0 if no error else -1;
- X*/
- X
- Xint readdir (direntry, zoo_file, fail) /* read directory entry */
- Xregister struct direntry *direntry;
- XZOOFILE zoo_file;
- Xint fail; /* 0 -> return, 1 -> abort on error */
- X{
- X if (frd_dir (direntry, zoo_file) < 0) {
- X if (fail) {
- X prterror ('f', bad_directory);
- X } else
- X return (-1);
- X }
- X if (direntry->zoo_tag != ZOO_TAG) {
- X if (fail)
- X prterror ('f', bad_directory);
- X else
- X return (-1);
- X }
- X return (0);
- X}
- X
- X/* use pointer version below */
- X#ifdef COMMENT
- X/* instr() searches a string for a substring */
- Xinstr (s, t) /* return index of string t in string s, -1 if none */
- Xchar s[], t[]; /* .. from K&R page 67 */
- X{
- X int i;
- X register int j, k;
- X for (i = 0; s[i] != '\0'; i++) {
- X for (j = i, k = 0; t[k] != '\0' && s[j]==t[k]; j++, k++)
- X ;
- X if (t[k] == '\0')
- X return (i);
- X }
- X return (-1);
- X}
- X#endif COMMENT
- X
- X/* instr() searches a string for a substring */
- X/* from J. Brian Waters */
- Xint instr (s, t) /* return the position of t in s, -1 if none */
- Xchar *s, *t; /* a pointer version of K&R index function p.67 */
- X{ /* renamed to instr() to avoid conflicts with C RTL - JBW */
- X
- X register char *i, *j, *k;
- X
- X for (i = s; *i; i++) {
- X for (j = i, k = t; (*k) && (*j++ == *k); k++)
- X ;
- X if (!*k)
- X return ((int) (i - s));
- X }
- X return(-1);
- X}
- X
- X/* cfactor() calculates the compression factor given a directory entry */
- Xint cfactor (org_size, size_now)
- Xlong org_size, size_now;
- X{
- X register int size_factor;
- X if ((unsigned long) org_size > 1000000) { /* avoid later overflow */
- X org_size = (unsigned long) org_size / 1024;
- X size_now = (unsigned long) size_now / 1024;
- X }
- X if (org_size == 0) /* avoid division by zero */
- X size_factor = 0;
- X else {
- X size_factor = (int)
- X (
- X (1000 *
- X ((unsigned long) org_size - (unsigned long) size_now)
- X ) / org_size + 5
- X ) / 10;
- X }
- X return (size_factor);
- X}
- X
- X#ifndef STRDUP
- X/***********
- Xstrdup() duplicates a string using dynamic memory.
- X*/
- X
- Xchar *strdup (str)
- Xregister char *str;
- X{
- X return (strcpy (emalloc (strlen(str)+1), str));
- X}
- X#endif /* STRDUP */
- X
- X/**************
- Xcmpnum() compares two pairs of unsigned integers and returns a negative,
- Xzero, or positive value as the comparison yields less than, equal, or
- Xgreater than result. Each pair of unsigned integers is considered to be the
- Xmore significant and the less significant half of a longer unsigned number.
- X
- XNote: cmpnum is used to compare dates and times.
- X*/
- X
- Xint cmpnum (hi1, lo1, hi2, lo2)
- Xregister unsigned int hi1, hi2;
- Xunsigned int lo1, lo2;
- X{
- X if (hi1 != hi2)
- X return (hi1 > hi2 ? 1 : -1);
- X else {
- X if (lo1 == lo2)
- X return (0);
- X else
- X return (lo1 > lo2 ? 1 : -1);
- X }
- X}
- X
- X/*******************/
- X/* writenull() */
- X/* writes a null directory entry to an open archive */
- Xvoid writenull (file, length)
- XZOOFILE file;
- Xint length;
- X{
- X#ifndef NOSIGNAL
- X int (*oldsignal)();
- X#endif
- X struct direntry newentry;
- X memset ((char *) &newentry, 0, sizeof (newentry));
- X newentry.zoo_tag = ZOO_TAG;
- X newentry.type = 2;
- X /* Force entry to be the required length plus possibly 2 stray bytes
- X by dividing up the needed padding into dirlen and namlen. */
- X if (length > SIZ_DIRL)
- X newentry.dirlen = newentry.namlen = (length-SIZ_DIRL)/2 + 2;
- X else
- X newentry.dirlen = newentry.namlen = 0;
- X#ifndef NOSIGNAL
- X oldsignal = signal (SIGINT, SIG_IGN);
- X#endif
- X if (fwr_dir (&newentry, file) == -1)
- X prterror ('f', disk_full);
- X#ifndef NOSIGNAL
- X signal (SIGINT, oldsignal);
- X#endif
- X}
- X
- X#ifdef FORCESLASH
- X/*******************/
- X/*
- Xfixslash() changes all "\" characters in the supplied string to "/".
- X*/
- X
- Xvoid fixslash (str)
- Xchar *str;
- X{
- X register char *p;
- X for (p = str; *p != '\0'; p++)
- X if (*p == '\\')
- X *p = '/';
- X}
- X#endif /* FORCESLASH */
- END_OF_FILE
- if test 9670 -ne `wc -c <'misc.c'`; then
- echo shar: \"'misc.c'\" unpacked with wrong size!
- fi
- # end of 'misc.c'
- fi
- if test -f 'vms.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'vms.c'\"
- else
- echo shar: Extracting \"'vms.c'\" \(9468 characters\)
- sed "s/^X//" >'vms.c' <<'END_OF_FILE'
- X#ifndef LINT
- X/* @(#) vms.c 1.4 87/07/26 22:48:45 */
- X/* @(#) vms.c 2.2 88/01/09 03:47:52 */
- X#endif /* LINT */
- X
- X/* machine.c for VMS */
- X
- X/****************
- XDate and time functions are standard UNIX-style functions, except that
- XVAX/VMS does not know about timezones. "nixtime.i" will be included
- Xby machine.c.
- X*/
- X
- X#include <stat.h>
- X#include <time.h>
- X
- X/* Function isuadir() returns 1 if the supplied filename is a directory,
- Xelse it returns 0.
- X*/
- X
- Xint isuadir (file)
- Xchar *file;
- X{
- X struct stat buf; /* buffer to hold file information */
- X if (stat (file, &buf) == -1) {
- X return (0); /* inaccessible -- assume not dir */
- X } else {
- X if (buf.st_mode & S_IFDIR)
- X return (1);
- X else
- X return (0);
- X }
- X}
- X
- X/****************
- XFunction fixfname() converts the supplied filename to a syntax
- Xlegal for the host system. It is used during extraction. We
- Xallow a maximum of one dot in the filename, and it must not
- Xbe at the beginning. We also truncate the number of charac-
- Xters preceding and following the dot to at most 39.
- X*/
- X
- Xchar *strchr();
- X
- Xchar *fixfname(fname)
- Xchar *fname;
- X{
- X char *p;
- X char *dotpos;
- X static char legal[] =
- X "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_.0123456789";
- X
- X /* convert all characters to legal characters */
- X for (p = fname; *p != '\0'; p++)
- X if (strchr (legal, *p) == 0) {
- X if (*p == '-' || *p == ' ')
- X *p = '_';
- X else
- X *p = legal [ *p % 26 ];
- X }
- X
- X /* first char can't be dot */
- X if (*fname == '.')
- X *fname = 'X';
- X
- X /* find embedded dot if any */
- X dotpos = strchr (fname, '.');
- X
- X if (dotpos != NULL) {
- X for (p = dotpos+1; *p != '\0'; p++) /* remove 2nd dot onwards */
- X if (*p == '.')
- X *p = '_';
- X if (dotpos - fname + 1 > 39) { /* more than 39 before dot not allowed */
- X char *q;
- X p = fname + 39;
- X q = dotpos;
- X while (*p++ = *q++) /* the notational convenience is considerable */
- X ;
- X dotpos = strchr (fname, '.');
- X }
- X if (strlen (dotpos + 1) > 39) /* more than 39 after dot not allowed */
- X *(dotpos + 39 + 1) = '\0';
- X } else
- X *(fname + 39) = '\0'; /* no dots, just truncate to 39 characters */
- X return (fname);
- X}
- X
- X/*
- XFunction gettz(), returns the offset from GMT in seconds of the
- Xlocal time, taking into account daylight savings time -- or it
- Xwould, if VAX/VMS knew about timezones! It's just a no-op.
- X*/
- Xlong gettz()
- X{
- X return 0L;
- X}
- X
- X/* Standard UNIX-compatible time functions */
- X#include "nixtime.i"
- X
- X/*
- XFunction utime() is just a stub. VMS C doesn't have it or
- Xan equivalent.
- X*/
- Xint utime (fname) char *fname; {}
- X
- X/*
- XFunction unlink() will delete a file using the VMS C delete()
- Xfunction.
- X*/
- Xint unlink (fname)
- Xchar *fname;
- X{
- X return (delete (fname));
- X}
- X
- X/*
- XFunction zooexit() receives attempts at exit. It always invokes
- Xexit() with status=1.
- X*/
- Xint zooexit (status)
- Xint status;
- X{
- X exit (1);
- X}
- X
- X
- X/*
- XFunction rename() renames a file.
- XThanks to Owen Anthony <bsu-cs!anthony>.
- X*/
- X
- X#include <descrip.h>
- X
- X#ifndef VMS_RENAME /* if not using VMS 4.6 library rename() */
- Xint rename (new_name, old_name)
- Xchar *new_name, *old_name;
- X{
- X int status;
- X struct dsc$descriptor_s file1, file2;
- X file1.dsc$w_length = strlen (old_name); /* descriptor for old name */
- X file1.dsc$a_pointer = old_name;
- X file1.dsc$b_class = DSC$K_CLASS_S;
- X file1.dsc$b_dtype = DSC$K_DTYPE_T;
- X file2.dsc$w_length = strlen (new_name); /* descriptor for new name */
- X file2.dsc$a_pointer = new_name;
- X file2.dsc$b_class = DSC$K_CLASS_S;
- X file2.dsc$b_dtype = DSC$K_DTYPE_T;
- X
- X status = LIB$RENAME_FILE (&file1, &file2);
- X
- X return ((status & ~1) == 1);
- X}
- X#endif /* VMS_RENAME */
- X
- X/*
- XFunction specfname() modifies filenames before they are stored
- Xin an archive. Currently we remove any trailing version field,
- Xand then any trailing dot.
- X*/
- Xchar *specfname (fname)
- Xchar *fname;
- X{
- X char *p;
- X p = strchr (fname, ';');
- X if (p != NULL)
- X *p = '\0';
- X if (*fname != '\0') {
- X p = fname + strlen (fname) - 1; /* point to last char */
- X if (*p == '.') /* remove any trailing dot */
- X *p = '\0';
- X }
- X return (fname);
- X}
- X
- X/*
- XFunction specdir() modifies directory names before they are stored
- Xin an archive. We remove any leading device name or logical
- Xname and and the [ and ] that bracket any directory name.
- XThen we change any dots in the directory name to slashes.
- X*/
- X
- X#if 0
- X/* test stub that just truncates dir to null string */
- Xchar *specdir (fname) char *fname;
- X{ *fname = '\0'; return (fname); }
- X#else
- X
- Xchar *specdir (fname)
- Xchar *fname;
- X{
- X char *p;
- X char tmpstr[LFNAMESIZE];
- X
- X p = strchr (fname, ':'); /* remove chars upto and including : */
- X if (p != NULL) {
- X strcpy (tmpstr, p+1);
- X strcpy (fname, tmpstr);
- X }
- X
- X p = strchr (fname, '['); /* remove chars upto and including [ */
- X if (p != NULL) {
- X strcpy (tmpstr, p+1);
- X strcpy (fname, tmpstr);
- X }
- X
- X p = strchr (fname, ']'); /* truncate at ] */
- X if (p != NULL) {
- X if (*(p+1) != '\0')
- X prterror ('w', "Trailing garbage in directory name\n");
- X *p = '\0';
- X }
- X
- X for (p = fname; *p != '\0'; p++) /* change dots to slashes */
- X if (*p == '.')
- X *p = '/';
- X
- X /* make sure there is a leading slash -- just a hack for now */
- X if (*fname != '/') {
- X strcpy (tmpstr, fname);
- X strcpy (fname, "/");
- X strcat (fname, tmpstr);
- X }
- X
- X#ifdef DEBUG
- Xprintf ("dir name transformed to \"%s\"\n", fname);
- X#endif
- X}
- X#endif
- X
- X#define FMAX 3 /* Number of different filename patterns */
- X
- Xchar *nextfile (what, filespec, fileset)
- Xint what; /* whether to initialize or match */
- Xregister char *filespec; /* filespec to match if initializing */
- Xregister int fileset; /* which set of files */
- X{
- X int status;
- X char *p; /* temp ptr */
- X struct dsc$descriptor_s d_fwild, d_ffound;
- X static int first_time [FMAX+1];
- X static char saved_fspec [FMAX+1][PATHSIZE]; /* our own copy of filespec */
- X static char found_fspec [FMAX+1][PATHSIZE]; /* matched filename */
- X static unsigned long context [FMAX+1]; /* needed by VMS */
- X if (what == 0) {
- X strcpy (saved_fspec[fileset], filespec); /* save the filespec */
- X first_time[fileset] = 1;
- X return (0);
- X }
- X
- X /* Reach here if what is not 0, so it must be 1 */
- X
- X /* Create a descriptor for the wildcarded filespec */
- X d_fwild.dsc$w_length = strlen (saved_fspec[fileset]);
- X d_fwild.dsc$a_pointer = saved_fspec[fileset];
- X d_fwild.dsc$b_class = DSC$K_CLASS_S;
- X d_fwild.dsc$b_dtype = DSC$K_DTYPE_T;
- X
- X d_ffound.dsc$w_length = sizeof (found_fspec[fileset]);
- X d_ffound.dsc$a_pointer = found_fspec[fileset];
- X d_ffound.dsc$b_class = DSC$K_CLASS_S;
- X d_ffound.dsc$b_dtype = DSC$K_DTYPE_T;
- X
- X if (first_time[fileset]) {
- X first_time[fileset] = 0;
- X context[fileset] = 0L; /* tell VMS this is first search */
- X }
- X status = LIB$FIND_FILE (&d_fwild, &d_ffound, &context[fileset]);
- X status = status & 1; /* use only lowest bit */
- X
- X if (status == 0) {
- X LIB$FIND_FILE_END (&context[fileset]);
- X return ((char *) 0);
- X } else {
- X found_fspec[fileset][d_ffound.dsc$w_length] = '\0'; /* just in case */
- X p = found_fspec[fileset];
- X while (*p != ' ' && *p != '\0')
- X p++;
- X if (*p != '\0')
- X *p = '\0';
- X return (found_fspec[fileset]);
- X }
- X}
- X
- X/*
- XFunction vmsmkdir() converts the received directory name into VMS
- Xformat and then creates a directory.
- X*/
- Xint vmsmkdir (subdir)
- Xchar *subdir;
- X{
- X char *lastptr();
- X char *p;
- X char tmp[LFNAMESIZE];
- X
- X p = subdir;
- X
- X /* leading "/" => "[", otherwise => "[." */
- X if (*p == '/') {
- X strcpy (tmp, "[");
- X p++;
- X } else {
- X strcpy (tmp, "[.");
- X while (*p == '/' || *p == '.')
- X p++;
- X }
- X
- X strcat (tmp, p);
- X
- X /*
- X VMS doesn't like dots in directory names, so we convert them to
- X underscores. Leave first two characters untouched, because
- X we don't want to corrupt a leading "[." into "[_".
- X */
- X for (p = tmp + 2; *p != '\0'; p++)
- X if (*p == '.')
- X *p = '_';
- X
- X /* convert all slashes to dots */
- X for (p = tmp; *p != '\0'; p++)
- X if (*p == '/')
- X *p = '.';
- X
- X /* Remove any trailing dot */
- X p = lastptr (tmp);
- X if (*p == '.')
- X *p = '\0';
- X
- X /* append closing bracket */
- X strcat (tmp, "]");
- X#if 0
- X printf ("\nmaking directory \"%s\"\n", tmp);
- X#endif
- X return (mkdir (tmp, 0));
- X}
- X
- X/*
- XFunction spec_wild() transforms a pattern supplied on the command line into one
- Xsuitable for wildcard expansion in the most efficient way possible. We change
- Xeach "?" to "%" but let "*" remain unchanged. We also append a ".*" if the
- Xpattern contains no dot, so "*" will be interpreted as "*.*" for VMS globbing.
- X*/
- Xchar *spec_wild (arg)
- Xchar *arg;
- X{
- X char *p;
- X#ifdef DEBUG
- X printf ("spec_wild: arg = [%s]\n", arg);
- X#endif
- X if (*lastptr (arg) == ']') /* add *.* if no filename */
- X strcat (arg, "*.*");
- X p = nameptr (arg); /* point p to filename part */
- X
- X /* if no dot in name append ".*" */
- X if (strchr (p, '.') == NULL)
- X strcat (p, ".*");
- X
- X for ( ; *p != '\0'; p++) /* change every "?" to "%" */
- X if (*p == '?')
- X *p = '%';
- X#ifdef DEBUG
- X printf ("spec_wild: arg changed to [%s]\n", arg);
- X#endif
- X return (arg);
- X}
- END_OF_FILE
- if test 9468 -ne `wc -c <'vms.c'`; then
- echo shar: \"'vms.c'\" unpacked with wrong size!
- fi
- # end of 'vms.c'
- fi
- if test -f 'zoo.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'zoo.c'\"
- else
- echo shar: Extracting \"'zoo.c'\" \(9863 characters\)
- sed "s/^X//" >'zoo.c' <<'END_OF_FILE'
- X#ifndef LINT
- X/* @(#) zoo.c 2.24 88/01/29 00:55:09 */
- Xstatic char sccsid[]="@(#) zoo.c 2.24 88/01/29 00:55:09";
- X#endif /* LINT */
- X
- X#if 0
- X#define TRACEI(item) printf("line %d: %s= %d\n", __LINE__, #item, item)
- X#define TRACES(item) printf("line %d: %s= [%s]\n", __LINE__, #item, item)
- X#endif
- X
- Xextern char version[];
- X
- X/*
- XCopyright (C) 1986, 1987 Rahul Dhesi -- All rights reserved
- X(C) Copyright 1988 Rahul Dhesi -- All rights reserved
- X*/
- X#include "options.h"
- X#include "zooio.h"
- X#include "various.h"
- X
- X#include "zoo.h"
- X#include "zoofns.h"
- X
- X#include "errors.i"
- X#include "zoomem.h"
- X
- X#ifdef TRACE_IO
- Xint verbose = 0;
- X#endif
- X
- X#ifdef LINT_ARGS
- Xint instr (char *, char *);
- X#else
- Xint instr ();
- X#endif
- X
- Xchar *out_buf_adr; /* points to memory allocated for output buffer(s) */
- Xchar *in_buf_adr; /* points to memory allocated for input buffer */
- X
- X/* static declarations */
- Xint quiet = 0; /* whether to be quiet */
- Xint next_arg = FIRST_ARG; /* filenames start at this position */
- Xint arg_count; /* count of arguments supplied to program */
- Xchar **arg_vector; /* vector of arguments supplied to program */
- X
- Xmain(argc,argv)
- Xregister int argc;
- Xregister char **argv;
- X{
- X char *zooname; /* synonym for argv[2] -- to make life easier */
- X#ifndef OOZ
- X static char incorrect_args[] = "Incorrect number of arguments.\n";
- X int filecount; /* how many filespecs supplied */
- X#endif /* OOZ */
- X
- X#ifdef OOZ
- X#else
- X/* else not OOZ */
- X static char usage[] = "Usage: zoo {acDeglLPTuUvx}[aAcCdEfInmMNoOpPqu1:/.@n] archive file\n(\"zoo h\" for help)\n";
- X static char nov_usage[] =
- X "\nNovice usage: zoo -cmd archive[.zoo] file... where -cmd is one of these:\n";
- X char *option;
- X
- X static char nov_cmds[] =
- X /* ADD=0EXT=5 MOV=14TES=20PRI=26 DEL=33 LIS=41UPD=47 FRE=55 COMMENT=64 */
- X "-add -extract -move -test -print -delete -list -update -freshen -comment\n";
- X
- X#ifdef NOENUM
- X#define NONE -1
- X#define ADD 0
- X#define EXTRACT 5
- X#define MOVE 14
- X#define TEST 20
- X#define PRINT 26
- X#define DELETE 33
- X#define LIST 41
- X#define UPDATE 47
- X#define FRESHEN 55
- X#define COMMENT 64
- X
- Xint cmd = NONE;
- X
- X#else
- X enum choice {
- X NONE=-1, ADD=0, EXTRACT=5, MOVE=14, TEST=20, PRINT=26,
- X DELETE=33, LIST=41, UPDATE=47, FRESHEN=55, COMMENT=64
- X };
- X enum choice cmd = NONE; /* assume no Novice command */
- X#endif
- X
- X#endif /* end of not OOZ */
- X
- X#ifdef SPECINIT
- X void spec_init PARMS ((NOTHING));
- X spec_init(); /* system-specific startup code */
- X#endif
- X
- X arg_count = argc;
- X arg_vector = argv;
- X zooname = argv[FIRST_ARG-1]; /* points to name or archive */
- X
- X#ifdef OOZ
- X if (argc < 2) {
- X putstr (usage1);
- X putstr (usage2);
- X zooexit (1);
- X }
- X#else
- X/* else not OOZ */
- X if (argc < 2)
- X goto show_usage;
- X filecount = argc - 3;
- X option = strdup(argv[1]);
- X
- X#ifdef TRACE_IO
- X if (*option == ':') { /* for debugging output */
- X verbose++;
- X option++; /* hide the : from other functions */
- X }
- X#endif
- X
- X#ifdef WAIT_PROMPT
- X if (*option == 'w') {
- X option++; /* hide w from other functions */
- X printf ("Hit RETURN when ready: ");
- X while (getchar() != '\n')
- X ;
- X }
- X#endif /* WAIT_PROMPT */
- X
- X if (*option == 'h' || *option == 'H')
- X goto bigusage;
- X if (strchr("-acDegflLPTuUvVx", *option) == NULL)
- X goto give_list;
- X
- X if (*option == '-') {
- X
- X#ifdef NOENUM
- X cmd = instr (nov_cmds, strlwr(option));
- X#else
- X cmd = (enum choice) instr (nov_cmds, strlwr(option));
- X#endif
- X
- X if (strlen(option) < 2 || cmd == NONE)
- X goto show_usage;
- X if ( ((cmd == ADD || cmd == MOVE || cmd == FRESHEN ||
- X cmd == UPDATE || cmd == DELETE) && argc < 4) ||
- X ((cmd == EXTRACT || cmd == TEST || cmd == LIST ||
- X cmd == PRINT || cmd == COMMENT) && argc < 3)) {
- X fprintf (stderr, incorrect_args);
- X goto show_usage;
- X }
- X } else {
- X char *wheresI; /* will be null if I option not supplied */
- X if (
- X (
- X strchr("au",*option) &&
- X (
- X (((wheresI = strchr(option,'I')) != 0) &&
- X argc != 3) ||
- X wheresI==NULL && argc < 4
- X )
- X ) ||
- X strchr("DU",*option) && argc < 4 ||
- X strchr("cexlvVL",*option) && argc < 3 ||
- X strchr("TP",*option) && argc != 3 ||
- X (*option == 'f' && argc != 2) ||
- X (*option == 'g' &&
- X (strchr(option,'A') == NULL && argc < 4 ||
- X strchr(option,'A') != NULL && argc != 3
- X )
- X )
- X ) {
- X fprintf (stderr, incorrect_args);
- X goto show_usage;
- X }
- X }
- X#endif /* end of not OOZ */
- X
- X#ifndef OOZ
- X /* if not doing a list and no extension in archive name, add default
- X extension */
- X if (*option != 'f' && cmd != LIST && strchr("lvVL", *option) == NULL &&
- X strchr(nameptr (zooname), EXT_CH) == NULL)
- X zooname = newcat (zooname, EXT_DFLT);
- X#endif
- X
- X/*
- XHere we allocate a large block of memory for the duration of the program.
- Xlzc() and lzd() will use half of it each. Routine getfile() will use all
- Xof it.
- X*/
- X/* fudge factor to avoid off-by-one errors */
- X#define FUDGE 10
- X
- X/* fudge/2 fudge/2
- X** [______________||________________|]
- X** output buffer input buffer
- X*/
- X out_buf_adr = emalloc (OUT_BUF_SIZE + IN_BUF_SIZE + FUDGE);
- X
- X /* input buffer is in top of allocated block */
- X in_buf_adr = out_buf_adr + OUT_BUF_SIZE + (FUDGE/2);
- X
- X#ifdef OOZ
- Xzooext(zooname, "\0"); /* just extract -- no fancy stuff */
- Xzooexit (0); /* and exit normally */
- X#else
- X/* else not OOZ -- parse command line and invoke a routine */
- X if (cmd != NONE) {
- X switch (cmd) {
- X
- X case ADD: zooadd (zooname, filecount, &argv[3], "aP:"); break;
- X case FRESHEN: zooadd (zooname, filecount, &argv[3], "auP:"); break;
- X case UPDATE: zooadd (zooname, filecount, &argv[3], "aunP:"); break;
- X case MOVE: zooadd (zooname, filecount, &argv[3], "aMP:"); break;
- X
- X case EXTRACT: zooext (zooname, "x"); break;
- X case TEST: zooext (zooname, "xNd"); break;
- X case PRINT: zooext (zooname, "xp"); break;
- X
- X case DELETE: zoodel (zooname, "DP",1); break;
- X case LIST: zoolist (&argv[2], "VC", argc-2); break;
- X case COMMENT: comment (zooname, "c"); break;
- X default: goto show_usage;
- X }
- X } else
- X switch (*option) {
- X
- X case 'a':
- X case 'u':
- X case 'T':
- X zooadd (zooname, filecount, &argv[3], option); break;
- X#ifdef FILTER
- X case 'f':
- X zoofilt (option); break;
- X#endif /* FILTER */
- X case 'D':
- X zoodel (zooname, option, 1); break;
- X case 'U':
- X zoodel (zooname, option, 0); break;
- X case 'g':
- X zoodel (zooname, option, 2); break;
- X case 'v':
- X case 'V':
- X case 'l':
- X zoolist(&argv[2], option, 1); break;
- X case 'L':
- X zoolist(&argv[2], option, argc-2); break;
- X case 'e':
- X case 'x':
- X zooext(zooname, option); break;
- X case 'P':
- X zoopack (zooname, option); break;
- X case 'c':
- X comment (zooname, option); break;
- X default:
- X goto give_list;
- X }
- Xzooexit (0); /* don't fall through */
- X
- X/* usage list including Novice commands */
- Xshow_usage:
- X fprintf (stderr, "%s%s%s", usage, nov_usage, nov_cmds); zooexit (1);
- X
- X/* brief usage list */
- Xgive_list:
- X fprintf (stderr, usage); zooexit (1);
- X
- X/* help screen */
- Xbigusage:
- X
- Xprintf ("Zoo archiver, %s\n", version);
- Xprintf("(C) Copyright 1988 Rahul Dhesi -- Noncommercial use permitted\n");
- X
- Xprintf (usage);
- Xprintf ("\nChoose a command from within {} and zero or more modifiers from within [].\n");
- X
- Xprintf ("E.g.: `zoo a save /bin/*' will archive all files in /bin into save.zoo.\n");
- Xprintf ("(Please see the user manual for a complete description of commands.)\n\n");
- X
- Xprintf (" Commands in {} mean: |Modifiers in [] mean:\n");
- X
- Xprintf (" a add files | a show archive name(s) in listing\n");
- Xprintf (" c update comments | A apply g or c to archive\n");
- Xprintf (" D delete stored files | c add/list comments\n");
- Xprintf (" e,x extract files | d extract/list deleted files too\n");
- Xprintf (" g adj. gen. limit/count | dd extract/list only deleted files\n");
- Xprintf (" l,L,v,V list filenames | E erase backup after packing\n");
- Xprintf (" P pack archive | f fast add (no compression) or list\n");
- Xprintf (" T fix archive datestamp | M move when adding (erase original)\n");
- Xprintf (" u add only newer files | n add only files not already in archive\n");
- Xprintf (" U undelete stored files | N send extracted data to Neverland\n");
- X#ifdef FILTER
- Xprintf (" f act as filter | c/u compress/uncompress as filter\n");
- X#endif /* FILTER */
- Xprintf (" ----------------------------- O don't ask \"Overwrite?\"\n");
- Xprintf (" q be quiet p pipe extracted data to standard output\n");
- Xprintf (" : don't store dir names /,// extract full pathnames\n");
- Xprintf (" . pack to current dir I add filenames read from stdin\n");
- Xprintf (" C show file CRC value +/- enable/disable generations\n");
- Xprintf (" S overwrite newer files g list generation limits\n");
- Xprintf (" P pack after adding @n start extract/list at position n\n");
- X
- X#ifdef FATTR
- Xprintf (" m list file modes OO overwrite read-only files\n");
- X#endif /* FATTR */
- X
- Xprintf (nov_usage);
- Xprintf (nov_cmds);
- X#endif /* end of not OOZ */
- X
- X/* NOTE: if allowed to fall through and return without an exit() statement,
- X it was printing garbage--corrupted stack? Why--bug in Microsoft C? */
- Xzooexit (1);
- X}
- END_OF_FILE
- if test 9863 -ne `wc -c <'zoo.c'`; then
- echo shar: \"'zoo.c'\" unpacked with wrong size!
- fi
- # end of 'zoo.c'
- fi
- echo shar: End of archive 5 \(of 10\).
- cp /dev/null ark5isdone
- MISSING=""
- for I in 1 2 3 4 5 6 7 8 9 10 ; do
- if test ! -f ark${I}isdone ; then
- MISSING="${MISSING} ${I}"
- fi
- done
- if test "${MISSING}" = "" ; then
- echo You have unpacked all 10 archives.
- rm -f ark[1-9]isdone ark[1-9][0-9]isdone
- else
- echo You still need to unpack the following archives:
- echo " " ${MISSING}
- fi
- ## End of shell archive.
- exit 0
-